#!/usr/bin/env ruby
require 'rubygems'
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
require "bundler/setup"
require 'rdf/rdfxml'
require 'rdf/turtle'
require 'rdf/ntriples'
require 'getoptlong'
require 'logger'
require 'open-uri'

def run(input, options)
  reader_class = RDF::Reader.for(options[:input_format].to_sym)
  raise "Reader not found for #{$input_format}" unless reader_class

  start = Time.new
  num = 0

  if options[:output_format] == :ntriples || options[:quiet]
    reader_class.new(input, options).each do |statement|
      num += 1
      if options[:quiet]
        #print "."
      else
        options[:output].puts statement.to_ntriples
      end
    end
  elsif options[:output_format] == :inspect
    reader_class.new(input, options).each do |statement|
      num += 1
      options[:output].puts statement.inspect
    end
  else
    r = reader_class.new(input, options)
    g = RDF::Repository.new << r
    num = g.count
    STDERR.puts "graph: #{g.dump(:ttl)}" if options[:verbose]
    options[:output].puts g.dump(options[:output_format], options.merge(prefixes: r.prefixes))
  end
  STDERR.puts
  secs = Time.new - start
  STDERR.puts "Parsed #{num} statements in #{secs} seconds @ #{num/secs} statements/second."
rescue
  fname = input.respond_to?(:path) ? input.path : "-stdin-"
  STDERR.puts("Error in #{fname}")
  raise
end

logger = Logger.new(STDERR)
logger.level = Logger::WARN
logger.formatter = lambda {|severity, datetime, progname, msg| "#{severity}: #{msg}\n"}

options = {
  input_format: :rdfxml,
  output: STDOUT,
  output_format: :ntriples,
  strict: true,
  validate: false,
  verbose: false,
  logger: logger
}
input = nil

opts = GetoptLong.new(
  ["--dbg", GetoptLong::NO_ARGUMENT],
  ["--execute", "-e", GetoptLong::REQUIRED_ARGUMENT],
  ["--format", GetoptLong::REQUIRED_ARGUMENT],
  ["--input-format", GetoptLong::REQUIRED_ARGUMENT],
  ["--output", "-o", GetoptLong::REQUIRED_ARGUMENT],
  ["--quiet", GetoptLong::NO_ARGUMENT],
  ["--template", GetoptLong::REQUIRED_ARGUMENT],
  ["--uri", GetoptLong::REQUIRED_ARGUMENT],
  ["--validate", GetoptLong::NO_ARGUMENT],
  ["--verbose", GetoptLong::NO_ARGUMENT],
)
opts.each do |opt, arg|
  case opt
  when '--dbg'            then logger.level = Logger::DEBUG
  when '--execute'        then input = arg
  when '--format'         then options[:output_format] = arg.to_sym
  when '--input-format'   then options[:input_format] = arg.to_sym
  when '--output'         then options[:output] = File.open(arg, "w")
  when '--quiet'
    options[:quiet] = true
    logger.level = Logger::FATAL
  when '--template'       then options[:haml] = arg.to_sym
  when '--uri'            then options[:base_uri] = arg
  when '--validate'       then options[:validate] = true
  when '--verbose'        then options[:verbose] = true
  when '--version'        then options[:version] = arg
  end
end

if ARGV.empty?
  s = input ? input : $stdin.read
  run(StringIO.new(s), options)
else
  ARGV.each do |test_file|
    run(Kernel.open(test_file), options)
  end
end
